<?php
/***************************************************************************
 *
 * Copyright (c) 2010 , Inc. All Rights Reserved
 * $Id$
 *
 **************************************************************************/

/**
 * @file Table.php
 * @author niulei(niulei@)
 * @date 2010/05/24 14:58:28
 * @version $Revision$
 * @brief
 *
 **/
abstract class Table {
	//数据库名称,子类需要重写这个属性
	protected $dbname;
	//数据库对象属性，应与数据库主表中字段对应
	protected $properties = array ();
	//扩展属性，为数据库字段不存在的扩展属性
	protected $exProperties = array ();
	//对象唯一属性,顺序比较重要，对应数据库主键属性
	protected $keyProperty = array ();
	//unique_id设置,可以与key property不同
	protected $uniqueId = '';
	//表名或虚表名,用于对象化操作,子类需要重写这个属性
	protected $table = '';
	//分表字段
	protected $tbSpProperty = NULL;
	//分表方法,
	protected $tbSpMethod = array();
	//已经更新过的属性和属性值，用来防止重覆更新
	private $updatedProperty = array ();
	//面向对象方式的数据操作对象，不允许外部进行修改
	private $db = NULL;
	//面向对象操作时的key与value对
	//设置成public是为了创建对象方便，db库内部会直接对他设置，外面不推荐使用这个
	public $arrValue = array();
	//magic方法
	function __get($key) {
		if(isset($this->arrValue[$key])){
			return $this->arrValue[$key];
		}else{
			if(isset($this->$key))
			return $this->$key;
			else
			return NULL;
		}
	}
	//magic方法
	function __set($key, $value) {
		$this->arrValue[$key] = $value;
		if(isset($key[2]) && 'v' == $key[0] && '_' == $key[2])
		$this->updatedProperty [$key] = 1;
	}

	function __isset($key){
		if(isset($this->arrValue[$key])){
			return true;
		}else{
			if(isset($this->$key)){
				return true;
			}else{
				return false;
			}
		}
	}

	function __unset($key){
		unset($this->arrValue[$key]);
		unset($this->$key);
	}

	function __sleep(){
		//只序列化properties和exProperties两个属性，方便之后的对象数据传递和反序列化
		return array('dbname','table','keyProperty','tbSpProperty','tbSpMethod','properties', 'exProperties');
	}
	function packData() {}
	function parseData() {}
	function setDb($db)
	{
		$this->db = $db;
	}

	private function initQuery(){
		if (!$this->db) {
			$this->db = Db::get($this->dbname);
		}
	}
	private function _innerGet($forUpdate)
	{
		$this->initQuery();
		$arr_res = $this->db->oGet($this,$forUpdate);
		if (isset ( $arr_res [0] )) {
			$this->arrValue = $arr_res[0];
			$this->__hit__ = true;
			$this->parseData();
		} else {
			$this->__hit__ = false;
		}
		return $this->__hit__;
	}
	public function getForUpdate()
	{
		return $this->_innerGet(true);
	}
	/**
	 * 从数据库查询数据，写入对象的属性值
	 */
	public function get() {
		return $this->_innerGet(false);
	}

	private function _innerUpdate($method)
	{
		$this->initQuery();
		$this->packData();
		$ret = $this->db->$method($this);
		$key = $this->uniqueId;
		if ($key && isset($ret[$key])) {
			$this->$key = $ret[$key];
		}
		return intval($ret['affected_rows']);
	}
	/**
	 * 更新对象属性值到数据库
	 */
	public function update() {
		return $this->_innerUpdate('oUpdate');
	}

	/**
	 * 把对象属性值插入数据表中
	 */
	public function insert() {
		return $this->_innerUpdate('oInsert');
	}

	/**
	 * 删除此对象对应数据库记录
	 */
	public function delete() {
		return $this->_innerUpdate('oDelete');
	}

	/**
	 * INSERT ON DUPLICATE KEY UPDATE的插入模式
	 */
	public function insertOrUpdate() {
		return $this->_innerUpdate('oInsertOrUpdate');
	}

	/**
	 * INSERT IGNORE INTO插入模式
	 */
	public function insertIgnore() {
		return $this->_innerUpdate('oInsertIgnore');
	}

	/**
	 * 获取插入对象后分配的唯一id
	 */
	public function getLastInsertId() {
		if (!$this->db) {
			throw new Exception('db.MustBeInsertFirst');
		}
		$id = $this->db->getLastInsertId();
		return $id;
	}

	/*
	 * array <=> object转换统一接口
	 */
	public function arrayToObject($arr_table) {
		foreach ( $arr_table as $key => $value ) {
			if(strlen($key)>2 && 'v' == $key[0] && '_' == $key[2]) {
				if(!empty($value) && $value != $this->$key){
					$this->updatedProperty [$key] = 1;
				}
			}
			//需考虑文本库字段的key返回，例如:vr_item_desc=>_vr_item_desc
			//if (in_array ( $key, $this->properties ) || in_array ( $key, $this->exProperties ) || in_array ( substr ( $key, 1 ), $this->properties ) || in_array ( substr ( $key, 1 ), $this->exProperties ))
			$this->arrValue[$key] = $value;
		}
		if (! empty( $arr_table )) {
			$this->__hit__ = true;
		} else {
			$this->__hit__ = false;
		}
	}

	public function objectToArray() {
		$arr_table = array ();
		foreach ( $this->properties as $value ) {
			if (NULL !== $this->$value)
			$arr_table [$value] = $this->$value;
		}
		foreach ( $this->exProperties as $value ) {
			if (NULL !== $this->$value)
			$arr_table [$value] = $this->$value;
		}
		return $arr_table;
	}

	public function __toString() {
		$object_str = '[db:'.$this->dbname.'][table:'.$this->table.']';
		$object_str .= '{Property}';
		foreach ( $this->properties as $value ) {
			if ($this->$value)
			$object_str .= '[' . $value . ':' . $this->$value . ']';
		}
		$object_str .= '{Ex_Property}';
		foreach ( $this->exProperties as $value ) {
			if ($this->$value)
			$object_str .= '[' . $value . ':' . $this->$value . ']';
		}
		return $object_str;
	}

	/**
	 * 清除属性修改记录
	 */
	public function clearUpdatedProperty() {
		$this->updatedProperty = array();
	}

	/**
	 * 检查属性是否被修改过
	 */
	public function checkUpdatedProperty($key){
		return isset($this->updatedProperty [$key]);
	}
}
